import pandas as pd
import os
from typing import List, Dict
from datetime import datetime
from core.models import FileInfo, ScanStatistics, CategoryStats, SoftwareInfo
from output.formatter import format_file_size, format_timestamp
from config.settings import EXCEL_SHEET_NAMES, SCAN_PATH

class ExcelReportGenerator:
    """Excel报表生成器"""
    
    def __init__(self):
        self.writer = None
        self.workbook = None
    
    def generate_report(self, 
                       file_list: List[FileInfo],
                       classified_files: Dict[str, List[FileInfo]],
                       category_stats: List[CategoryStats],
                       scan_stats: ScanStatistics,
                       output_path: str = "scan_result.xlsx",
                       software_list: List[SoftwareInfo] = None):
        """生成Excel报表
        
        Args:
            file_list: 文件信息列表
            classified_files: 分类后的文件字典
            category_stats: 分类统计信息
            scan_stats: 扫描统计信息
            output_path: 输出文件路径
        """
        
        with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
            self.writer = writer
            self.workbook = writer.book
            
            # 生成各个工作表
            self._create_summary_sheet(scan_stats, category_stats)
            self._create_file_list_sheet(file_list)
            self._create_category_sheet(category_stats)
            self._create_directory_sheet(file_list)
            self._create_large_files_sheet(file_list)
            
            # 如果有软件识别结果，创建软件信息工作表
            if software_list and len(software_list) > 0:
                self._create_software_sheet(software_list)
    
    def _create_summary_sheet(self, scan_stats: ScanStatistics, category_stats: List[CategoryStats]):
        """创建总览工作表"""
        summary_data = {
            '统计项目': [
                '扫描路径', '扫描时间', '扫描时长', 
                '总文件数', '总目录数', '总大小',
                '扫描速度', '错误数量'
            ],
            '数值': [
                SCAN_PATH,
                scan_stats.scan_time,
                f"{scan_stats.scan_duration:.2f} 秒",
                scan_stats.total_files,
                scan_stats.total_directories,
                format_file_size(scan_stats.total_size),
                f"{scan_stats.files_per_second:.1f} 文件/秒",
                scan_stats.error_count
            ]
        }
        
        df_summary = pd.DataFrame(summary_data)
        df_summary.to_excel(self.writer, sheet_name=EXCEL_SHEET_NAMES['summary'], index=False)
        
        # 分类统计
        category_data = []
        for stats in category_stats:
            if stats.file_count > 0:
                percentage = (stats.total_size / scan_stats.total_size * 100) if scan_stats.total_size > 0 else 0
                category_data.append({
                    '分类': stats.category_name,
                    '文件数量': stats.file_count,
                    '总大小': stats.size_display,
                    '平均大小': stats.avg_size_display,
                    '占比': f"{percentage:.2f}%"
                })
        
        if category_data:
            df_category = pd.DataFrame(category_data)
            df_category.to_excel(self.writer, sheet_name=EXCEL_SHEET_NAMES['summary'], 
                               startrow=len(summary_data) + 3, index=False)
    
    def _create_file_list_sheet(self, file_list: List[FileInfo]):
        """创建文件明细表"""
        file_data = []
        for file_info in file_list:
            if not file_info.is_directory:  # 只列出文件，不包含目录
                file_data.append({
                    '文件名': file_info.name,
                    '路径': file_info.path,
                    '大小': file_info.size_display,
                    '类型': file_info.extension,
                    '分类': file_info.category,
                    '创建时间': format_timestamp(file_info.created_time),
                    '修改时间': format_timestamp(file_info.modified_time),
                    '是否为系统文件': '是' if file_info.is_system_file else '否',
                    '是否为大文件': '是' if file_info.is_large_file else '否'
                })
        
        if file_data:
            df_files = pd.DataFrame(file_data)
            df_files.to_excel(self.writer, sheet_name=EXCEL_SHEET_NAMES['file_list'], index=False)
    
    def _create_category_sheet(self, category_stats: List[CategoryStats]):
        """创建分类统计表"""
        category_data = []
        for stats in category_stats:
            if stats.file_count > 0:
                category_data.append({
                    '分类名称': stats.category_name,
                    '文件数量': stats.file_count,
                    '总大小': stats.size_display,
                    '平均文件大小': stats.avg_size_display
                })
        
        if category_data:
            df_categories = pd.DataFrame(category_data)
            df_categories.to_excel(self.writer, sheet_name=EXCEL_SHEET_NAMES['categories'], index=False)
    
    def _create_directory_sheet(self, file_list: List[FileInfo]):
        """创建目录统计表"""
        # 首先初始化所有目录
        dir_data = {}
        for file_info in file_list:
            if file_info.is_directory:
                dir_path = file_info.path
                if dir_path not in dir_data:
                    dir_data[dir_path] = {
                        'file_count': 0,
                        'total_size': 0,
                        'depth': file_info.depth
                    }
        
        # 优化版：一次遍历计算目录统计
        # 1. 先统计直接文件数和大小
        for file_info in file_list:
            if not file_info.is_directory:  # 只处理文件
                if file_info.parent_path in dir_data:
                    dir_data[file_info.parent_path]['file_count'] += 1
                    dir_data[file_info.parent_path]['total_size'] += file_info.size
        
        # 2. 使用路径字典批量更新父目录大小
        # 先按深度排序，确保子目录先处理
        sorted_dirs = sorted(dir_data.keys(), key=lambda x: dir_data[x]['depth'], reverse=True)
        
        for dir_path in sorted_dirs:
            parent_path = os.path.dirname(dir_path)
            if parent_path in dir_data:
                # 将子目录的大小累加到父目录
                dir_data[parent_path]['total_size'] += dir_data[dir_path]['total_size']
        
        # 转换为DataFrame
        dir_list = []
        for path, data in dir_data.items():
            dir_list.append({
                '目录路径': path,
                '文件数量': data['file_count'],
                '总大小': format_file_size(data['total_size']),
                '深度': data['depth']
            })
        
        if dir_list:
            df_dirs = pd.DataFrame(dir_list)
            # 按总大小降序排序
            df_dirs = df_dirs.sort_values(by='文件数量', ascending=False)
            df_dirs.to_excel(self.writer, sheet_name=EXCEL_SHEET_NAMES['directories'], index=False)
    
    def _create_large_files_sheet(self, file_list: List[FileInfo]):
        """创建大文件列表"""
        large_files = [f for f in file_list if f.is_large_file and not f.is_directory]
        large_files.sort(key=lambda x: x.size, reverse=True)
        
        large_file_data = []
        for file_info in large_files:
            large_file_data.append({
                '文件名': file_info.name,
                '路径': file_info.path,
                '大小': file_info.size_display,
                '类型': file_info.extension,
                '分类': file_info.category,
                '修改时间': format_timestamp(file_info.modified_time)
            })
        
        if large_file_data:
            df_large = pd.DataFrame(large_file_data)
            df_large.to_excel(self.writer, sheet_name=EXCEL_SHEET_NAMES['large_files'], index=False)
    
    def _create_software_sheet(self, software_list: List[SoftwareInfo]):
        """创建软件信息工作表"""
        # 按置信度排序
        sorted_software = sorted(software_list, key=lambda x: x.confidence, reverse=True)
        
        # 创建数据框
        software_data = []
        for software in sorted_software:
            software_data.append({
                '软件名称': software.name,
                '版本': software.version,
                '发布商': software.publisher,
                '安装路径': software.install_path,
                '安装日期': format_timestamp(software.install_date) if software.install_date else '-',
                '文件数量': software.file_count,
                '总大小': software.size_display,
                '分类': software.category,
                '置信度': f"{software.confidence_score:.2f}",
                '主可执行文件': software.main_executable if software.main_executable else '-',
                '特征文件数量': len(software.signature_files) if software.signature_files else 0
            })
        
        if software_data:
            df_software = pd.DataFrame(software_data)
            df_software.to_excel(self.writer, sheet_name=EXCEL_SHEET_NAMES['software'], index=False)